用mirrormaker在多个数据中心做Kafka的数据同步还需要考虑几个问题:
如何提高同步效率?
跨数据中心的数据传输,瓶颈在于带宽。我们采取的办法是启多个mirrormaker进程和压缩。
在两台机器间带宽固定的情况下,理论上在多台机器上启多个mirrormaker进程能扩大总带宽。但在实际应用中的效果,还要看具体的网络配置
Kafka本身支持GZIP,Snappy和LZ4压缩协议。从我的测试结果来看,LZ4压缩和解压效率最高,GZIP压缩率最高,具体还是要看数据格式。
mirrormaker部署在哪?
将数据从数据中心A同步到数据中心B,mirrormaker部署在A端(Source端)或者B端(Destination端)都可以,但还是会有点区别。
LinkedIn建议部署在Destination端。对于跨数据中心的数据同步来说,最不稳定的因素就是网络,我们需要保证的,是在网络断开的情况下不丢数据或者丢尽量少的数据。mirrormaker本质上是consumer + cache + producer,offset在放进cache之后就commit,因此mirrormaker部署在Destination端的好处显而易见,假如数据中心间的网络出了问题,mirrormaker根本就收不到数据,也就不存在丢数据的问题;但如果部署在Source端,网络出问题之后,mirrormaker consumer仍然能够从本地Kafka集群获取数据放进cache中,并commit offset,但数据并没有成功的produce到Destination端,mirrormaker也不再有机会重新获取数据。
我个人建议是部署在Source端。原因很简单,为了压缩。我们压缩的目的是为了数据在producer远程传输的过程中能尽量的减少带宽占用,如果部署在Destination端,mirrormaker consumer消费的是原始数据,并没有节省带宽。
如果数据本身是压缩过的,mirrormaker怎么处理?
理想情况下,我们应该直接把压缩的数据传输到远端,但现在mirrormaker内置的consumer会在消费后先把数据解压缩,然后producer发送前再把数据压缩。
这样对CUP的消耗很大且不必要,当至少到现在为止Kafka还没有给出解决办法。
如何保证数据有序?
只有满足以下条件才能保证partition内数据有序:
- 同步的数据是keyed的
- mirrormaker和数据原来的producer使用相同的partitioner
- Source topic和Destination topic的partition数目相同
双向同步?
mirrormaker不支持相同topic的双向同步。如果这么做了,会导致数据在两个Kafka集群之间无限的重复同步,因为mirrormaker并不能判断一条数据是被普通producer发进来的还是之前被它自己从另一个数据中心同步过来的。
我的建议是,用上一篇文章说的聚合集群。如果不想这么大动干戈,也可以用不同的topic后缀来区分,比如topicA_sh,topicA_bj,保证数据不会被重复同步。
或者有个更简单但不是很合理的做法。强制在所有的数据的key中划分出一段来专门记录数据被发送到的数据中心名字,然后在MirrorMakerMessageHandler中解析key,判断是否需要同步。比如如果发现一条数据来自shanghai,那么beijing到shanghai的mirrormaker不会对它做同步。这种做法对数据格式有很强的侵入性,所以不是很建议。其实个人认为如果给kafka record本身加上metamap就能解决这个问题。